package com.zifan.sever.service.impl;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zifan.sever.bean.*;
import com.zifan.sever.constant.MailConstants;
import com.zifan.sever.mapper.EmployeeMapper;
import com.zifan.sever.service.*;
import com.zifan.sever.utils.RespBean;
import com.zifan.sever.utils.RespPageBean;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zifan
 * @since 2021-04-10
 */
@Service
@Slf4j
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements IEmployeeService {

    @Autowired
    private EmployeeMapper employeeMapper;

    /**
     * 民族
     */
    @Autowired
    private INationService nationService;

    /**
     * 政治面貌
     */
    @Autowired
    private IPoliticsStatusService politicsStatusService;

    /**
     * 部门
     */
    @Autowired
    private IDepartmentService departmentService;

    /**
     * 职称
     */
    @Autowired
    private IJoblevelService joblevelService;

    /**
     * 职位
     */
    @Autowired
    private IPositionService positionService;

    @Autowired
    private ISalaryService salaryService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private IMailLogService mailLogService;

    /**
     * 获取员工列表，并进行分页
     * @param currentPage 当前页
     * @param size 一页几条
     * @param employee 员工对象 为了查询
     * @param beginDateScope 日期范围，是个数组
     * @return
     */
    @Override
    public RespPageBean getEmployeesWithPage(Integer currentPage, Integer size, Employee employee, LocalDate[] beginDateScope) {
        Page<Employee> page = new Page<>(currentPage, size);
        //注意，这里employeeMapper.getEmployeesWithPage的返回值虽然是IPage，但是其实没有用
        //我记得是这样的，测试也通过了。是这样的，上面的那个page在执行下面这个分页查询的时候，查询完毕后会自动设置到上面的page里面去
        //所以不需要在使用这个IPage接受了
        IPage<Employee> employeesWithPage = employeeMapper.getEmployeesWithPage(page, employee, beginDateScope);
        //这里直接使用了page，上面的那个employeesWithPage其实是没用的，为了笔记暂且保留
        return new RespPageBean(page.getTotal(), page.getRecords());
    }

    /**
     * 不分页获取所有员工列表
     * @param id 如果不传测查全部，传了则根据id查询
     * @return
     */
    @Override
    public List<Employee> getEmployees(Integer id) {
        return this.baseMapper.getEmployees(id);
    }

    /**
     * 获取工号
     * @return
     */
    @Override
    public RespBean getmaxWorkID() {
        QueryWrapper<Employee> wrapper = new QueryWrapper<>();
        wrapper.select("max(workID) as maxID");
        /**
         * 查询sql select max(workID) as maxID from t_employee;
         * 结果是一个map的数组，这个数组只有一个map
         * 然后+1并且转换成string返回出去
         * 这里的String.format("%80d", maxID);中"%08d"的意思是
         * 加入这个数是99，转化后就变成00000099
         */
        List<Map<String, Object>> maps = this.baseMapper.selectMaps(wrapper);
        String maxID = (String)maps.get(0).get("maxID");
        String s = String.format("%08d", Integer.parseInt(maxID)+1);
        return RespBean.success(null,s);
    }

    /**
     * 添加员工
     * @param employee
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public RespBean addEmp(Employee employee) {
        //合同开始日期
        LocalDate beginContract = employee.getBeginContract();
        //合同结束日期
        LocalDate endContract = employee.getEndContract();
        //计算两者相差几天
        long interval = beginContract.until(endContract, ChronoUnit.DAYS);

        //之后让这个数除以365，保留两位小数
        //todo 这里需要详细的笔记
        DecimalFormat decimalFormat = new DecimalFormat("##.00");
        String format = decimalFormat.format(interval/365.00);
        //contractTerm 合同期限
        double contractTerm = Double.parseDouble(format);
        employee.setContractTerm(contractTerm);

        //然后正常插入
        if (this.save(employee)){
            Employee employeeById = this.baseMapper.getEmployees(employee.getId()).get(0);

            //确保消息发送成功 1、消息发送是先落库
            MailLog mailLog = new MailLog();
            String msgId = IdUtil.simpleUUID();
            mailLog.setMsgId(msgId);
            mailLog.setEid(employeeById.getId());
            //0消息投递中
            mailLog.setStatus(0);
            mailLog.setRouteKey(MailConstants.MAIL_ROUTING_KEY_NAME);
            mailLog.setExchange(MailConstants.MAIL_EXCHANGE_NAME);
            mailLog.setCount(0);
            mailLog.setTryTime(LocalDateTime.now().plusMinutes(MailConstants.MSG_TIMEOUT));
            mailLog.setCreateTime(LocalDateTime.now());
            mailLog.setUpdateTime(LocalDateTime.now());
            mailLogService.save(mailLog);

            //准备发送邮件 向消息队列中发送消息

            //这是一个hello world模型 Employee需要实现序列化
            rabbitTemplate.convertAndSend(MailConstants.MAIL_EXCHANGE_NAME,
                    MailConstants.MAIL_ROUTING_KEY_NAME,
                    employeeById,
                    //消息确认参数，msgID为消息在数据库中的主键
                    new CorrelationData(msgId));
            return RespBean.success("添加成功");
        }

        return RespBean.error("添加失败");
    }

    /**
     * 导出员工列表
     * @param response
     */
    @Override
    public void exportEmp(HttpServletResponse response) {
        List<Employee> employees = this.getEmployees(null);
        //导出
        ExportParams params = new ExportParams("员工表", "员工表", ExcelType.HSSF);
        Workbook workbook = ExcelExportUtil.exportExcel(params, Employee.class, employees);
        //准备一个流开始响应
        ServletOutputStream outputStream = null;
        try {
            //流形式
            response.setHeader("content-type","application/octet-stream");
            //设置文件名字以及防止中文乱码
            response.setHeader("content-disposition","attachment;filename=" +
                    URLEncoder.encode("员工信息表.xls","UTF-8"));
            outputStream = response.getOutputStream();
            workbook.write(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ObjectUtil.isNotNull(outputStream)){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 导入员工列表
     * @param file
     * @return
     */
    @Override
    public RespBean importEmp(MultipartFile file) {
        ImportParams importParams = new ImportParams();
        //设置读取的excel的第一行是表头，然后不读取
        importParams.setTitleRows(1);
        //获取全部的民族
        List<Nation> nationList = nationService.list();
        //获取全部的政治面貌
        List<PoliticsStatus> politicsStatusList = politicsStatusService.list();
        //获取全部的部门
        List<Department> departmentList = departmentService.list();
        //获取全部的职称
        List<Joblevel> joblevelList = joblevelService.list();
        //获取全部的职位
        List<Position> positionList = positionService.list();
        List<Employee> targetList = null;
        try {
            targetList = ExcelImportUtil.importExcel(file.getInputStream(), Employee.class, importParams);
            //todo 这样逆天的代码，需要加上点判断！
            for (Employee employee : targetList) {
                employee.setNationId(
                        nationList.get(nationList.indexOf(employee.getNation())).getId()
                );
/*                for (Nation nation : nationList) {
                    if (employee.getNation().getName().equals(nation.getName())){
                        employee.setNationId(nation.getId());
                    }
                }*/
                employee.setPoliticId(
                        politicsStatusList.get(politicsStatusList.indexOf(employee.getPoliticsStatus())).getId()
                );
                employee.setDepartmentId(
                        departmentList.get(departmentList.indexOf(employee.getDepartment())).getId()
                );
                employee.setJobLevelId(
                        joblevelList.get(joblevelList.indexOf(employee.getJoblevel())).getId()
                );
                employee.setPosId(
                        positionList.get(positionList.indexOf(employee.getPosition())).getId()
                );
            }
            log.info("组合后列表：{}",targetList);
            if (this.saveBatch(targetList)){
                return RespBean.success("导入成功");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return RespBean.error("导入失败，请联系管理员");
//        return RespBean.success("成功",targetList);
    }

    /**
     * 分页获取所有的员工带着套账
     * 这里我不写sql了，吐了。用mybatisplus直接做了
     * @param currentPage
     * @param size
     * @return
     */
    @Override
    public RespPageBean getEmpWithSalary(Integer currentPage, Integer size) {
        Page<Employee> page = new Page<>(currentPage, size);
        this.page(page);
        List<Employee> resList = page.getRecords();
        for (Employee emp : resList) {
            emp.setSalary(salaryService.getById(emp.getSalaryId()));
            emp.setDepartment(departmentService.getById(emp.getDepartmentId()));
        }
        return new RespPageBean(page.getTotal(),resList);
    }
}
